package tailfile

import (
	"github.com/sirupsen/logrus"
	"logagent/common"
)

//管理tailTask管理者
type tailTaskMgr struct {
	tailTaskMap      map[string]*tailTask       //所有tailTask任务
	collectEntryList []common.CollectEntry      //所有的配置项
	confChan         chan []common.CollectEntry //等待新配置的通道
}

var (
	ttMgr *tailTaskMgr
)

//tail相关  main函数中调用
func Init(allConf []common.CollectEntry) (err error) {
	//allConf里面存若干个日志的收集项
	//针对每一个日志收集项创建一个对应的tObj
	ttMgr = &tailTaskMgr{
		tailTaskMap:      make(map[string]*tailTask, 20),
		collectEntryList: allConf,
		confChan:         make(chan []common.CollectEntry), //做一个阻塞的chan
	}
	for _, conf := range allConf {
		//创建一个日志收集任务
		tt := newTailTask(conf.Path, conf.Topic)
		err = tt.Init()
		if err != nil {
			logrus.Errorf("tailfile:create tailObj for path: %s failed,err:%v \n", conf.Path, err)
			continue
		}
		logrus.Infof("create a tail task for path:%s success", conf.Path)
		ttMgr.tailTaskMap[tt.path] = tt //把创建的这个tailTask任务登记注册
		//去收集日志吧
		go tt.run()
	}
	go ttMgr.watch() //在后台中等新的配置来
	return
}

func (t *tailTaskMgr) watch() {
	for {
		//初始化新配置的管道,做一个阻塞的chan
		//派一个小弟等着新的配置来，
		newConf := <-t.confChan //取到值说明新的配置来啦
		//新配置来了，应该管理之前启动的那些tailTask
		logrus.Infof("get new conf from etcd ,newConf:%v,start manager tailTask... \n", newConf)

		for _, conf := range newConf {
			//1.原来已经存在的任务不用动
			if t.isExist(conf) {
				continue
			}
			//2.原来没有的要新创建一个tailTask
			tt := newTailTask(conf.Path, conf.Topic)
			err := tt.Init()
			if err != nil {
				logrus.Errorf("tailfile:create  tailObj for path: %s failed,err:%v \n", conf.Path, err)
				continue
			}
			logrus.Infof("create a tail task for path:%s success", conf.Path)
			ttMgr.tailTaskMap[tt.path] = tt //把创建的这个tailTask任务登记注册
			//去收集日志吧
			go tt.run()
		}
		//3.原来有的,现在没有的要tailTask停掉
		//找出tailTaskMap中存在，但是newConf不存在的那些tailTask,把他们停掉
		for key, task := range t.tailTaskMap {
			var found bool
			for _, conf := range newConf {
				if key == conf.Path {
					found = true
					break
				}
			}
			if !found {
				//没有找到，这个tailTask要停掉
				logrus.Infof("the task collect path:%s need to stop \n", task.path)
				delete(t.tailTaskMap, key)
				task.cancel()
			}
		}
	}
}

//判断tailTaskMap是否存在该收集项
func (t *tailTaskMgr) isExist(conf common.CollectEntry) bool {
	_, ok := t.tailTaskMap[conf.Path]
	return ok
}

func SendNewConf(newConf []common.CollectEntry) {
	ttMgr.confChan <- newConf
}
